Skip to content

Add OpenRTB 2.6 proto types#390

Open
ChristianPavilonis wants to merge 22 commits intomainfrom
feature/openrtb-full-implementation
Open

Add OpenRTB 2.6 proto types#390
ChristianPavilonis wants to merge 22 commits intomainfrom
feature/openrtb-full-implementation

Conversation

@ChristianPavilonis
Copy link
Collaborator

@ChristianPavilonis ChristianPavilonis commented Mar 2, 2026

Summary

  • Replace hand-written OpenRTB types with spec-compliant generated types from the official IAB Tech Lab protobuf schema, ensuring full OpenRTB 2.6 coverage including DOOH, GPP, Qty, Refresh, and DurFloors fields.
  • Enrich Prebid bid requests with many more OpenRTB fields derived from available auction data — bid floors, device signals, user consent, geo, regs/privacy, site referrer, and request-level defaults.

Changes

File Change
crates/openrtb/Cargo.toml New crate (edition 2024) with serde, serde_json — no prost runtime dep
crates/openrtb/proto/openrtb.proto OpenRTB 2.6 proto2 schema from IAB Tech Lab upstream
crates/openrtb/src/generated.rs Checked-in generated code (1566 lines) — no build-time protoc needed
crates/openrtb/src/codegen.rs Postprocessing logic (strip prost derives, inject serde, add ext fields) with 7 unit tests
crates/openrtb/src/lib.rs bool_as_int serde module (6 edge-case tests), ToExt supertrait, explicit re-exports, deserialization tests
crates/openrtb/generate.sh Bash wrapper to regenerate from proto using the codegen crate
crates/openrtb/README.md Crate documentation
crates/openrtb-codegen/ Standalone codegen crate (excluded from workspace) with prost-build dependency
crates/common/src/openrtb.rs Replace ~180 lines of hand-written structs with type aliases; shared to_openrtb_i32() helper; opt-in ToExt impls for 4 ext types
crates/common/src/geo.rs GDPR_COUNTRIES set (EU/EEA/UK), is_gdpr_country() function with 5 tests
crates/common/src/integrations/prebid.rs Enrich bid requests with bid floors, device signals, consent, geo, regs, site fields; DEFAULT_CURRENCY and GPC_US_PRIVACY constants; language subtag stripping; typed get_prebid_ext() test helper; 17+ tests
crates/common/src/auction/formats.rs Update response construction for generated types with Option wrappers and ToExt
crates/common/Cargo.toml Add trusted-server-openrtb dependency
Cargo.toml Add openrtb to workspace members, exclude openrtb-codegen, remove prost-build from workspace deps
Cargo.lock Dependency additions (serde derives for openrtb)
.github/workflows/format.yml Removed protoc install step (no longer needed)
.github/workflows/test.yml Removed protoc install step (no longer needed)

Key design decisions

  • No prost runtime dependency: Generated code has prost::Enumeration and alloc types stripped during postprocessing, so the openrtb crate only depends on serde.
  • Checked-in generated code: Avoids requiring protoc in CI/dev environments. Regenerate via ./generate.sh when the proto changes.
  • GDPR via geo check: Uses Fastly geo.country_code() to determine GDPR applicability (EU/EEA/UK country list) rather than parsing TCF consent strings. Falls back to consent string presence when geo is unavailable.
  • ToExt as supertrait: ToExt: Serialize with opt-in impls on the 4 Prebid ext types, preventing accidental misuse.

Test plan

  • cargo test --workspace — all tests pass
  • cargo clippy --all-targets --all-features -- -D warnings
  • cargo fmt --all -- --check
  • JS tests: cd crates/js/lib && npx vitest run
  • JS format: cd crates/js/lib && npm run format
  • Docs format: cd docs && npm run format

@ChristianPavilonis ChristianPavilonis linked an issue Mar 2, 2026 that may be closed by this pull request
@ChristianPavilonis ChristianPavilonis changed the title DRAFT: OpenRTB full implementation Add complete OpenRTB 2.6 data model crate Mar 3, 2026
@ChristianPavilonis ChristianPavilonis force-pushed the feature/openrtb-full-implementation branch from f2eee35 to 0c0e4fa Compare March 3, 2026 16:01
@ChristianPavilonis ChristianPavilonis marked this pull request as ready for review March 5, 2026 02:03
@aram356 aram356 marked this pull request as draft March 5, 2026 16:18
@ChristianPavilonis ChristianPavilonis changed the title Add complete OpenRTB 2.6 data model crate Generate OpenRTB 2.6 types from IAB proto with full field enrichment Mar 5, 2026
Enrich outgoing Prebid Server requests with fields that were already
available in the AuctionRequest/context but not being mapped:

- Imp: bidfloor/bidfloorcur (from AdSlot.floor_price), secure (1),
  tagid (slot id)
- Geo: lat/lon (from GeoInfo), metro (DMA code)
- User: consent (TCF consent string from UserInfo)
- Regs: gdpr flag (when consent present), us_privacy promoted to
  first-class field
- Device: dnt (from DNT header), language (from Accept-Language)
- Site: ref (from Referer header), publisher object with domain
- BidRequest: tmax (from config timeout_ms), cur (["USD"])

Also refactor build_openrtb_request to use a params struct to satisfy
clippy argument limits, and fix pre-existing test compilation errors
where ext fields were accessed with struct syntax instead of Map::get.
- Validate Sec-GPC header value is '1' (not just presence)
- Add comment documenting GDPR flag trade-off (conservative approach)
- Add comment about hardcoded USD currency
- Remove dead RegsExt struct (us_privacy promoted to first-class field)
- Remove unnecessary language.clone()
- Add 13 tests covering all new OpenRTB field mappings: bidfloor,
  secure, tagid, consent/gdpr, Sec-GPC, DNT, language, geo lat/lon/
  metro, tmax, cur, site.ref, site.publisher
Debug logging is only enabled in testing environments, so redacting
sensitive fields (consent, IP, geo, referer) before logging adds
complexity without meaningful privacy benefit. Log the request directly.
@ChristianPavilonis ChristianPavilonis force-pushed the feature/openrtb-full-implementation branch from 77539cf to b3480cd Compare March 5, 2026 19:53
@ChristianPavilonis ChristianPavilonis marked this pull request as ready for review March 5, 2026 20:02
@ChristianPavilonis ChristianPavilonis marked this pull request as draft March 5, 2026 20:02
@ChristianPavilonis ChristianPavilonis marked this pull request as ready for review March 5, 2026 20:07
@ChristianPavilonis ChristianPavilonis marked this pull request as draft March 5, 2026 20:15
@ChristianPavilonis ChristianPavilonis marked this pull request as ready for review March 6, 2026 03:17
Copy link
Collaborator

@aram356 aram356 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(superseded — see latest review below)

Copy link
Collaborator

@aram356 aram356 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Staff Engineer Review

Overall this is a solid change — introducing a proto-generated OpenRTB crate is the right call for spec compliance, and the enrichment of the bid request with consent, DNT, language, geo, floor prices, etc. is well-tested and well-commented.

Findings below use the code review emoji guide.

Summary

Emoji Finding
🔧 build.rs text munging has no tests — add unit tests for postprocess()
🔧 Duplicated i32 conversion logic — extract shared helper
🔧 GDPR applicability inferred from consent string presence — can misclassify non-EEA traffic
🤔 prost runtime dep is unnecessary — strip prost::Enumeration or accept the bloat
🤔 ToExt blanket impl too broad — narrow to ext-relevant types
🤔 device.language keeps locale tag instead of primary language
🤔 Consider checking in generated code — eliminates protoc build dependency
🌱 Sec-GPC → us_privacy "1YYN" hardcoded — consider making configurable
Edition mismatch (2021 vs 2024)
Hardcoded "USD" / "1YYN" — extract named constants
pub use generated::* + manual re-exports redundancy
bool_as_int edge case tests
📌 CI protoc install is uncached and somewhat fragile

@ChristianPavilonis ChristianPavilonis changed the title Generate OpenRTB 2.6 types from IAB proto with full field enrichment Add OpenRTB 2.6 proto types and fix store name constants Mar 6, 2026
@ChristianPavilonis ChristianPavilonis force-pushed the feature/openrtb-full-implementation branch from 47d2a4b to b939bbf Compare March 6, 2026 13:23
@ChristianPavilonis ChristianPavilonis changed the title Add OpenRTB 2.6 proto types and fix store name constants Add OpenRTB 2.6 proto types Mar 6, 2026
…eo check, extract constants, and improve test coverage

- Strip prost::Enumeration from codegen, remove prost runtime dependency
- Replace prost alloc type paths with std equivalents in generated code
- Narrow ToExt from blanket impl to opt-in supertrait with provided method
- Remove pub use generated::*, use explicit re-exports only
- Fix edition 2021 -> 2024 in openrtb crate
- Add GDPR geo check (EU-27 + EEA + UK) via is_gdpr_country() in geo.rs
- Fall back to consent-string heuristic only when geo is unavailable
- Extract DEFAULT_CURRENCY and GPC_US_PRIVACY named constants
- Strip locale subtag from device.language (en-US -> en)
- Extract shared to_openrtb_i32() helper, deduplicate formats.rs/prebid.rs
- Add typed get_prebid_ext() test helper for compile-time field safety
- Move postprocess() to src/codegen.rs shared between build.rs and tests
- Add 7 codegen tests, 8 bool_as_int/deserialization tests, 5 geo tests, 3 GDPR tests
…DPR, cleanup

- bool_as_int: accept string "1"/"0"/"true"/"false" from bidders
- codegen: document brace-counting assumption for prost output
- geo: use LazyLock<HashSet> for O(1) GDPR country lookups
- remove unused prost workspace dependency (only prost-build is used)
- replace dead unwrap_or with expect in language parsing
- CI: use arduino/setup-protoc@v3 for cached protoc installs
Move proto codegen from build.rs to an on-demand generate.sh script
backed by a standalone openrtb-codegen crate (workspace-excluded).
The checked-in src/generated.rs means normal builds and CI no longer
need protoc installed — only developers editing the proto file do.

- Delete build.rs, replace include!(OUT_DIR) with mod generated
- Add crates/openrtb-codegen as excluded workspace member
- Add crates/openrtb/generate.sh wrapper script
- Remove prost-build from workspace deps and openrtb build-deps
- Remove protoc install steps from CI workflows
@ChristianPavilonis
Copy link
Collaborator Author

Review Response Summary

All 14 review comments have been addressed across 3 commits. Here's what changed:

Commit 1: f07ed22 — Core review fixes

  1. Remove prost runtime dependency — Stripped prost::Enumeration derive + methods from generated code, replaced ::prost::alloc::{string::String, vec::Vec} with std equivalents. prost is no longer a dependency of the openrtb crate.
  2. Narrow ToExt blanket impl — Changed from a blanket impl<T: Serialize> ToExt for T to a supertrait ToExt: Serialize with opt-in impls on the 4 ext types (PrebidExt, PrebidBidExt, PrebidImpExt, PrebidBidderExt).
  3. GDPR from geo, not consent string — Replaced TCF consent-string parsing with is_gdpr_country() geo check using Fastly's geo.country_code() (EU/EEA/UK list). Falls back to checking consent string presence when geo is unavailable.
  4. Extract constants"USD"DEFAULT_CURRENCY, "1YYN"GPC_US_PRIVACY with documentation explaining the value and a note about future configurability.
  5. Language subtag strippingdevice.language now strips subtags (en-USen) per OpenRTB spec.
  6. Typed ext test helperget_prebid_ext() now deserializes into PrebidExt struct instead of raw serde_json::Value.
  7. Edition 2024 — Updated crates/openrtb/Cargo.toml from edition = "2021" to edition = "2024".

Commit 2: d0c18bc — Additional hardening

  1. bool_as_int edge cases — Added 6 tests: null, string values, negative numbers, and round-trip serialization.
  2. Minimal deserialization tests — Tests for empty {} JSON and unknown fields to verify resilience.
  3. HashSet for GDPR countries — Switched from sorted array + binary search to LazyLock<HashSet> for O(1) lookups.

Commit 3: 0be0e0c — Check in generated code

  1. Check in generated codesrc/generated.rs (1566 lines) is now committed. Deleted build.rs.
  2. Separate codegen crate — Created crates/openrtb-codegen/ (excluded from workspace) with prost-build dependency. A generate.sh script wraps the regeneration workflow.
  3. Removed protoc from CI — Stripped protoc install steps from format.yml and test.yml workflows.
  4. pub use generated::* → explicit re-exportslib.rs now uses mod generated; with explicit generated:: prefixed paths only.

Also fixed

  • Shared to_openrtb_i32() helper in common/openrtb.rs to eliminate duplicated u32 → i32 conversion logic.
  • Extracted build.rs postprocessing logic into codegen.rs with 7 unit tests, shared via include!() between the openrtb crate (for testing) and the codegen crate (for generation).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Complete OpenRTB implementation

2 participants